﻿using JetBrains.Annotations;
using System;
using System.Security.Cryptography;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;

namespace Elvex
{
    public class SceneRequest
    {
        public string Name { get; private set; }

        public event UnityAction<Scene, LoadSceneMode> Loaded;

        internal SceneRequest(string name)
        {
            Name = name;
            Debug.Log(Name);
            Elvex.Instance.ScenesManager.AddSceneRequest(this);
        }

        internal SceneRequest(int index):
            this(string.Format("elvex@scene_{0}", index))
        {

        }

        internal void OnSceneLoaded(Scene scene, LoadSceneMode mode)
        {
            if (null != Loaded)
            {
                Loaded(scene, mode);
            }
            else
            {
                Debug.LogWarning("OnSceneLoaded is null");
            }
        }
    }

    public class SceneAsyncRequest : SceneRequest
    {
        internal AsyncOperation operation;
        
        public event Action<AsyncOperation> Completed;

        internal SceneAsyncRequest(string name, AsyncOperation opera):
            base(name)
        {
            operation = opera;
            operation.completed += Completed;
        }

        internal SceneAsyncRequest(int index, AsyncOperation opera):
            base(index)
        {
            operation = opera;
            operation.completed += Completed;
        }

        internal float GetProgress()
        {
            return operation.progress;
        }
    }

    public class SceneParameters
    {
        internal LoadSceneMode LoadMode { get; } = LoadSceneMode.Single;

        internal UnityAction<Scene, LoadSceneMode> Loaded { get; }

        public SceneParameters(LoadSceneMode mode)
        {
            LoadMode = mode;
        }

        public SceneParameters(UnityAction<Scene, LoadSceneMode> loadedaction)
        {
            Loaded = loadedaction;
        }

        public SceneParameters(LoadSceneMode mode, UnityAction<Scene, LoadSceneMode> loadedaction)
        {
            LoadMode = mode;
            Loaded = loadedaction;
        }
    }

    public static class Scenes
    {
        public static bool Load(string name)
        {
            return Load(name, new LoadSceneParameters(LoadSceneMode.Single), null);
        }

        public static bool Load(string name, LoadSceneParameters parameters)
        {

            return Load(name, parameters, null);
        }

        public static bool Load(string name, UnityAction<Scene, LoadSceneMode> loadedaction)
        {
            return Load(name, new LoadSceneParameters(LoadSceneMode.Single), loadedaction);
        }

        public static bool Load(string name, LoadSceneParameters parameters, UnityAction<Scene, LoadSceneMode> loadedaction)
        {
            SceneRequest req = new SceneRequest(name);
            if (null != loadedaction)
            {
                req.Loaded += loadedaction;
            }

            if (null == UnityEngine.SceneManagement.SceneManager.LoadScene(name, parameters))
            {
                return false;
            }
            return true;
        }

        public static SceneAsyncRequest LoadAsync(string name)
        {
            return LoadAsync(name, new LoadSceneParameters(LoadSceneMode.Single));
        }

        public static SceneAsyncRequest LoadAsync(string name, LoadSceneMode mode)
        {
            return LoadAsync(name, new LoadSceneParameters(mode));
        }

        public static SceneAsyncRequest LoadAsync(string name, LoadSceneParameters parameters)
        {
            return new SceneAsyncRequest(name, SceneManager.LoadSceneAsync(name, parameters));
        }
    }
}



